/**
 * Created by IntelliJ IDEA.
 * Time: 23:56
 *
 * @Author: xyb
 * @Version: 2017/6/29
 * To change this template use File | Settings | File Templates.
 */
package blog.web.websocket;

import blog.sys.entity.ChatMsg;
import blog.sys.entity.User;
import blog.sys.service.ChatMsgService;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.socket.*;

import java.io.IOException;
import java.net.URLEncoder;
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

@Component
public class MyWebSocketHandler implements WebSocketHandler {
    //当MyWebSocketHandler类被加载时就会创建该Map，随类而生
    public static final Map<Integer, WebSocketSession> userSocketSessionMap;

    private static final Log log = LogFactory.getLog(MyWebSocketHandler.class);

    static {
        userSocketSessionMap = new HashMap<Integer, WebSocketSession>();
    }

    //握手实现连接后
    @Override
    public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {
        //将当前的连接的用户会话放入MAP,key是用户编号
        User loginUser = (User) webSocketSession.getAttributes().get("loginUser");
        userSocketSessionMap.put(loginUser.getId(), webSocketSession);
        //群发消息告知大家
        ChatMsg msg = new ChatMsg();
        msg.setContent(loginUser.getNickName() + ":踩着轻盈的步伐来啦。。。大家欢迎！!");
        msg.setCreateTime(new Date());
        //获取所有在线的WebSocketSession对象集合
        Set<Entry<Integer, WebSocketSession>> entrySet = userSocketSessionMap.entrySet();
        //将最新的所有的在线人列表放入消息对象的list集合中，用于页面显示
        for (Entry<Integer, WebSocketSession> entry : entrySet) {
            User user = (User) entry.getValue().getAttributes().get("loginUser");
            msg.getUserList().add(user);
        }
        /*
        //将消息转换为json
        TextMessage message = new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(msg));
        //群发消息
        sendMessageToAll(message);
        */
    }


    //发送信息前的处理
    @Override
    public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception {
        if (webSocketMessage.getPayloadLength() == 0) {
            return;
        }
        //得到Socket通道中的数据并转化为Message对象
        ChatMsg msg = new Gson().fromJson(webSocketMessage.getPayload().toString(), ChatMsg.class);

        Timestamp now = new Timestamp(System.currentTimeMillis());
        msg.setCreateTime(now);

        Integer voiceId = chatMsgService.save(msg);
        msg.setVoiceFileId(voiceId);
        if (msg.getToUserId() != null && !msg.getToUserId().equals("-1")) {// 单发
            //发送Socket信息
            sendMessageToUser(msg.getUserId(), msg.getToUserId(), new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(msg)));
        } else {//群发
            sendMessageToAll(new TextMessage(new GsonBuilder().create().toJson(msg)));
        }
    }

    /**
     * 消息传输过程中出现的异常处理函数
     * 处理传输错误：处理由底层WebSocket消息传输过程中发生的异常
     */
    @Override
    public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) throws Exception {
        // 记录日志，准备关闭连接
        System.out.println("Websocket异常断开:" + webSocketSession.getId() + "已经关闭");
        if (webSocketSession.isOpen()) {
            webSocketSession.close();
        }
    }

    /**
     * websocket链接关闭的回调
     * 连接关闭后：一般是回收资源等
     */
    @Override
    public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
        // 记录日志，准备关闭连接
        System.out.println("Websocket正常断开:" + webSocketSession.getId() + "已经关闭");

        //群发消息告知大家
        ChatMsg msg = new ChatMsg();
        msg.setCreateTime(new Date());
        User loginUser = (User) webSocketSession.getAttributes().get(MyHandShakeInterceptor.SOCKET_SEESION);
        Set<Entry<Integer, WebSocketSession>> entrySet = userSocketSessionMap.entrySet();
        //并查找出在线用户的WebSocketSession（会话），将其移除（不再对其发消息了。。）
        for (Entry<Integer, WebSocketSession> entry : entrySet) {
            if (entry.getKey().equals(loginUser.getId())) {
                //群发消息告知大家
                msg.setContent("万众瞩目的【" + loginUser.getNickName() + "】已经有事先走了，大家继续聊...");
                //清除在线会话
                userSocketSessionMap.remove(entry.getKey());
                //记录日志：
                System.out.println("Socket会话已经移除:用户ID" + entry.getKey());
                break;
            }
        }
        //
        for (Entry<Integer, WebSocketSession> entry : entrySet) {
            msg.getUserList().add((User) entry.getValue().getAttributes().get("loginUser"));
        }
        /*
        TextMessage message = new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(msg));
        sendMessageToAll(message);
        */
    }

    /**
     * 是否支持处理拆分消息，返回true返回拆分消息
     */
    //是否支持部分消息：如果设置为true，那么一个大的或未知尺寸的消息将会被分割，并会收到多次消息（会通过多次调用方法handleMessage(WebSocketSession, WebSocketMessage). ）
    //如果分为多条消息，那么可以通过一个api：org.springframework.web.socket.WebSocketMessage.isLast() 是否是某条消息的最后一部分。
    //默认一般为false，消息不分割
    @Override
    public boolean supportsPartialMessages() {
        return false;
    }


    // 群发
    private void sendMessageToAll(final TextMessage message) {
        Set<Entry<Integer, WebSocketSession>> entrySet = userSocketSessionMap.entrySet();
        for (Entry<Integer, WebSocketSession> entry : entrySet) {
            final WebSocketSession webSocketSession = entry.getValue();
            if (webSocketSession.isOpen()) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            if (webSocketSession.isOpen()) {
                                webSocketSession.sendMessage(message);
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        }
    }

    //发送单独信息的实现
    public void sendMessageToUser(int userId, int toId, TextMessage message)
            throws IOException {

        WebSocketSession session = userSocketSessionMap.get(toId);//对方
        if (session != null && session.isOpen()) {
            session.sendMessage(message);
        }
        WebSocketSession session1 = userSocketSessionMap.get(userId);
        if (session1 != null && session1.isOpen()) {
            session1.sendMessage(message);
        }
    }

    @Autowired
    private ChatMsgService chatMsgService;
}
